#define BIN_FILE_READ 0
#define BIN_FILE_WRITE 1
#define BIN_FILE_APPEND 2

typedef unsigned long long Int64;
typedef unsigned long Int32;
typedef unsigned char Int8;

class BinFile {
private:
  FILE *link;
  long size;
public:
  BinFile() {
    link = NULL;
  }
  long getSize() {
    return size;
  }
  void open(string filename, int mode) {
    if (mode == BIN_FILE_READ) {
      link = fopen(filename.c_str(), "rb");
      fseek(link, 0, SEEK_END);
      size = ftell(link);
      fseek(link, 0, SEEK_SET);
    } else if (mode == BIN_FILE_WRITE) {
      link = fopen(filename.c_str(), "wb");            
      size = 0;
    } else {
      // TODO сделать правильную обработку append file
      link = fopen(filename.c_str(), "ab");            
      fseek(link, 0, SEEK_END);
      size = ftell(link);      
    }
  }
  ~BinFile() {
    fclose(link);
  }
  bool isEnd() {
    return feof(link);
  }
  bool isOpen() {
    return link != NULL;
  }
  int skip(long offset) {
    return fseek(link, offset, SEEK_SET);
  }
  template<class T> void write(T v) {
    fwrite((char*)&v, sizeof(T),1, link);
    size += sizeof(T);
  }
  template<class T>
  void readblock(T* a, long size) {
    fread((char*)a, sizeof(T), size, link);
  }
  template<class T> void read(T &v) {
    fread((char*)&v, sizeof(T), 1, link);
  }
};

class BoolNumber {
public:
  Int64 a;
  BoolNumber(Int64 b) {
    a = b;    
  }
};

vector<Int8> tv;

ostream& operator << (ostream& stream, BoolNumber a) {
  tv.resize(0);
  if (a.a == 0) tv.push_back(0);
  while (a.a != 0) {
    tv.push_back( (a.a & 1) );
    a.a >>= 1;    
  }
  for(size_t i = tv.size(); i--; ) stream << (int)tv[i];
  return stream;
}

ostream& operator << (ostream& stream, vector<Int8> &a) {
  for (size_t i = 0; i < a.size(); i++) {
    stream << (int)a[i];
    if (i + 1 != a.size()) stream << ' ';
  }
  return stream;
}

template<class T>
ostream& operator << (ostream& stream, vector<T> &a) {
  for (size_t i = 0; i < a.size(); i++) {
    stream << a[i];
    if (i + 1 != a.size()) stream << ' ';
  }
  return stream;
}

